package br.com.lm.view;

import br.com.lm.base.eao.EaoException;
import br.com.lm.entity.CtrlUsuario;
import br.com.lm.filter.QuestionarioSenha;
import br.com.lm.geral.util.EnviaEmail;
import br.com.lm.geral.util.GerenciamentoLoginBean;
import br.com.lm.geral.util.MessageProvider;
import br.com.lm.geral.util.MsgCtrlBean;
import java.io.Serializable;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIInput;
import javax.faces.component.UISelectOne;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import org.apache.commons.mail.EmailException;
import org.primefaces.context.RequestContext;

public class RecuperarSenhaBean implements Serializable {

    private static final long serialVersionUID = 1L;
    
    //Controle de acao 
    private static final String RECUPERAR_SENHA_ESQUECIDA  = "1";
    private static final String DEFINIR_PERGUNTA_REC_SENHA = "2";
    
    //Componentes de tela
    private static final String UISELECTONE_ID_PERGUNTAS = "recupSenhaForm:j_idt8:perguntas";
    private static final String UIINPUT_ID_DOCTOCPF    = "recupSenhaForm:j_idt8:doctoCPF";
    private static final String UIINPUT_ID_RESPPERGUNTA = "recupSenhaForm:j_idt8:respPergunta";
 
    //Internacionalizacao
    private static final String LOGIN_RESOURCE_BUNDLE_VAR  = "msgLogin";
    private static final String SYSTEM_RESOURCE_BUNDLE_VAR = "msgPool";    
    private MessageProvider messageProvider; 
    private String resourceBundleVar;

    //Validacao de alteracao de login
    private GerenciamentoLoginBean ctrlAtualizacaoLogin;
    private CtrlUsuario dadosUsuario;
    
    //Mensagens
    FacesMessage msgRtrn;
    String mensagem;
    
    //Area de input/output com pagina de recuperar_senha.jsf
    private String acao;
    private String username;    
    private String nomUser;       
    private String password;
    
    private String nrDocumento;    
    private String pergunta; 
    private String resposta; 
    private QuestionarioSenha questionario;

    //CallbackParam - pojo as json    
    private boolean onOffAdmSenhas;   
    
    //Getter's e Setter's publicos
    public boolean isOnOffAdmSenhas() {
        return onOffAdmSenhas;
    }

    public void setOnOffAdmSenhas(boolean onOffAdmSenhas) {
        this.onOffAdmSenhas = onOffAdmSenhas;
    }

    public String getAcao() {
        return acao;
    }

    public void setAcao(String acao) {
        this.acao = acao;
    }
    
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
    
    public String getNomUser() {
        return nomUser;
    }

    public void setNomUser(String nomUser) {
        this.nomUser = nomUser;
    }

    public String getNrDocumento() {
        return nrDocumento;
    }

    public void setNrDocumento(String nrDocumento) {
        this.nrDocumento = nrDocumento;
    }

    public String getPergunta() {
        return pergunta;
    }

    public void setPergunta(String pergunta) {
        this.pergunta = pergunta;
    }

    public String getResposta() {
        return resposta;
    }

    public void setResposta(String resposta) {
        this.resposta = resposta;
    }

    public QuestionarioSenha getQuestionario() {
        return questionario;
    }

    public void setQuestionario(QuestionarioSenha questionario) {
        this.questionario = questionario;
        if (acao.equals(DEFINIR_PERGUNTA_REC_SENHA) && this.questionario != null)
            pergunta = questionario.getPergunta();
    }
    
    /* -----------------------------------------------------------------------
     * Acao para recuperar senha ou criar ajuda de recuperacao 
     * ---------------------------------------------------------------------- */
    public void acaoAdmSenhas() throws EaoException {
        onOffAdmSenhas = false;
        resourceBundleVar = LOGIN_RESOURCE_BUNDLE_VAR;
        msgRtrn = null; 
        ctrlAtualizacaoLogin = new GerenciamentoLoginBean();       
        
        if (acao.equals(RECUPERAR_SENHA_ESQUECIDA)) {
            //Validar Usuario (sem a necessidade da senha)
            dadosUsuario = ctrlAtualizacaoLogin.getCtrlUsuarioById(username);
            if (dadosUsuario == null) {
                //Código de usuário inválido
                mensagem = MsgCtrlBean.getMessageFrmt(getMessageI18N("E006"), new String[]{getMessageI18N("I007")});
                msgRtrn = new FacesMessage(FacesMessage.SEVERITY_ERROR, null, mensagem);
            }
            else {
                nomUser = dadosUsuario.getNomUsuario();
                if (dadosUsuario.getDscPergunta() == null || dadosUsuario.getDscPergunta().trim().equals("")) {
                    //Não existe pergunta para recuperação de senha! Entrar em contato com administrador do sistema.
                    msgRtrn = new FacesMessage(FacesMessage.SEVERITY_ERROR, null, getMessageI18N("E007"));
                }
                else 
                if (dadosUsuario.getDscEmail() == null || dadosUsuario.getDscEmail().trim().equals("")) {
                    //Não existe email cadastrado para o login! Entrar em contato com administrador do sistema.
                    msgRtrn = new FacesMessage(FacesMessage.SEVERITY_ERROR, null, getMessageI18N("E008"));
                }    
                else {
                    //Limpa documento para preenchimento e move questionario
                    nrDocumento = null;
                    resposta    = null;
                    pergunta = dadosUsuario.getDscPergunta();
                }
            }
        }
        else 
        if (acao.equals(DEFINIR_PERGUNTA_REC_SENHA)) {
            //Usuario e senha tem de estar validado
            if (password == null || password.trim().equals("")) {
                //Campo "Senha" é de preenchimento obrigatório para ação escolhida
                mensagem = MsgCtrlBean.getMessageFrmt(getMessageI18N("E005"), new String[]{getMessageI18N("I008")});
                msgRtrn = new FacesMessage(FacesMessage.SEVERITY_ERROR, null, mensagem);
            }
            else {
                msgRtrn = ctrlAtualizacaoLogin.validaLogin(username, password);
                if (msgRtrn == null) {
                    dadosUsuario = ctrlAtualizacaoLogin.getUsuarioAutenticado();
                    nomUser = dadosUsuario.getNomUsuario();
                    nrDocumento = dadosUsuario.getCpfOuCnpj();
                    resposta = null;
                    pergunta = null;
                    //Salva dados de sessão do Usuario autenticado 
                    //msgRtrn = ctrlAtualizacaoLogin.sucessoLogin(true, false);
                }
            }
        }   
        
        //Global Messages
        if (msgRtrn != null) 
            FacesContext.getCurrentInstance().addMessage(null, msgRtrn);
        else onOffAdmSenhas = true; 
        
        //Notifica o java script evento: "oncomplete="tabAccordionOnOff(xhr, status, args)"
        RequestContext context = RequestContext.getCurrentInstance();  
        context.addCallbackParam("onOffAdmSenhas", onOffAdmSenhas); 
    }

    /* -----------------------------------------------------------------------
     * Atualiza Base Administração de senhas (Nova Senha e/ou Nova Ajuda)
     * ---------------------------------------------------------------------- */    
     public void atlzAdmSenhas() throws EaoException {
        String keyLoginMsgSucesso = null;
        msgRtrn  = null; 
        mensagem = null;
        
        if (acao.equals(RECUPERAR_SENHA_ESQUECIDA)) {  
            keyLoginMsgSucesso = "S202";
            novaSenha();
        }    
        else 
        if (acao.equals(DEFINIR_PERGUNTA_REC_SENHA)) {    
           keyLoginMsgSucesso = "S201"; 
           ajudaSenha();
        }        
            
        //Notifica o java script evento: "oncomplete="sucessAtlzAdmSenhas(xhr, status, args)"
        RequestContext context = RequestContext.getCurrentInstance();  
        context.addCallbackParam("isOkAdmSenhas", msgRtrn == null ? true : false); 
        
        //Verifica status do processamento
        if (msgRtrn == null) {
            resourceBundleVar = LOGIN_RESOURCE_BUNDLE_VAR;
            msgRtrn = new FacesMessage(FacesMessage.SEVERITY_INFO, getNomUser(), getMessageI18N(keyLoginMsgSucesso));
        } 
                    
        //Global Messages
        FacesContext.getCurrentInstance().addMessage(null, msgRtrn);
    }
    
    /* -----------------------------------------------------------------------
     * Gerar uma nova senha a ser enviado por email
     * ---------------------------------------------------------------------- */    
    private void novaSenha() throws EaoException {
        resourceBundleVar = LOGIN_RESOURCE_BUNDLE_VAR;
        msgRtrn = null; 
        
        //Componentes de tela
        UIViewRoot uiv = FacesContext.getCurrentInstance().getViewRoot();
        UIInput uii;
        boolean isOk = true;    
        
        //Verifica campos de preenchimento obrigatórios
        if ( nrDocumento == null || nrDocumento.trim().equals("")) {
            uii = (UIInput) uiv.findComponent(UIINPUT_ID_DOCTOCPF);
            uii.setValid(false);
            isOk = false;
        }  
        if (resposta == null || resposta.trim().equals("")) {
            uii = (UIInput) uiv.findComponent(UIINPUT_ID_RESPPERGUNTA);
            uii.setValid(false);
            isOk = false;
        }        
        
        //Confronta valores com base de dados
        if (isOk) {
            if (dadosUsuario.getCpfOuCnpj() != null && !dadosUsuario.getCpfOuCnpj().trim().equals("")) {
                if (!dadosUsuario.getCpfOuCnpj().equals(nrDocumento)) {
                    uii = (UIInput) uiv.findComponent(UIINPUT_ID_DOCTOCPF);
                    uii.setValid(false);
                    isOk = false;   
                    mensagem = MsgCtrlBean.getMessageFrmt(getMessageI18N("E201"), new String[]{getMessageI18N("I300")});
                    msgRtrn = new FacesMessage(FacesMessage.SEVERITY_ERROR, null, mensagem);
                }
            }
            if (isOk) {
                if (dadosUsuario.getDscResposta() != null && !dadosUsuario.getDscResposta().trim().equals("")) {
                    if (!dadosUsuario.getDscResposta().toLowerCase().equals(resposta.toLowerCase())) {
                        uii = (UIInput) uiv.findComponent(UIINPUT_ID_RESPPERGUNTA);
                        uii.setValid(false);
                        mensagem = MsgCtrlBean.getMessageFrmt(getMessageI18N("E201"), new String[]{getMessageI18N("I301")});
                        msgRtrn = new FacesMessage(FacesMessage.SEVERITY_ERROR, null, mensagem); 
                    }
                }    
            }
        } 
        else {    
            msgRtrn = new FacesMessage(FacesMessage.SEVERITY_ERROR, null, getMessageI18N("W001"));            
        }
        
        //Atualiza base de dados com senha padrão e envia email
        if (msgRtrn == null) {
            //Atualizar senha e documento para o padrao
            String senhaAleatoria = getNovaSenhaRandom();
            Map<String,Object> mapColVlr = new HashMap<String, Object>(2); 
            mapColVlr.put("Cpf_Ou_Cnpj",  nrDocumento);
            mapColVlr.put("Psw_Usuario", senhaAleatoria);
            ctrlAtualizacaoLogin.updCtrlUsuarioById(dadosUsuario.getCodUsuario(), mapColVlr);
            enviaEmail(senhaAleatoria); 
        }
    }

    /* -----------------------------------------------------------------------
     * Criar ajuda para recuperacao de senha
     * ---------------------------------------------------------------------- */            
    private void ajudaSenha() throws EaoException {
        resourceBundleVar = LOGIN_RESOURCE_BUNDLE_VAR;
        msgRtrn = null; 
        //Componentes de tela
        UIViewRoot uiv = FacesContext.getCurrentInstance().getViewRoot();
        UIInput uii;
        UISelectOne uiso;
        boolean isOk = true;    
        //Verifica campos de preenchimento obrigatórios
        if ( nrDocumento == null || nrDocumento.trim().equals("")) {
            uii = (UIInput) uiv.findComponent(UIINPUT_ID_DOCTOCPF);
            uii.setValid(false);
            isOk = false;
        }  
        if (pergunta == null || pergunta.trim().equals("")) {
            uiso = (UISelectOne)uiv.findComponent(UISELECTONE_ID_PERGUNTAS);            
            if (questionario != null)
                pergunta = questionario.getPergunta();
            else 
            if (uiso.getValue() != null) 
                pergunta = uiso.getValue().toString();
            //Foi possivel recuperar do questionario ou do componente de tela? 
            if (pergunta == null || pergunta.trim().equals("")) {
                uiso.setValid(false);
                isOk = false;
            }    
        }
        if (resposta == null || resposta.trim().equals("")) {
            uii = (UIInput) uiv.findComponent(UIINPUT_ID_RESPPERGUNTA);
            uii.setValid(false);
            isOk = false;
        }        
        //Grava hint para recuperação de senha
        if (isOk) {
            Map<String,Object> mapColVlr = new HashMap<String, Object>(2); 
            mapColVlr.put("Cpf_Ou_Cnpj",  nrDocumento);
            mapColVlr.put("Dsc_Pergunta", pergunta);
            mapColVlr.put("Dsc_Resposta", resposta);
            ctrlAtualizacaoLogin.updCtrlUsuarioById(dadosUsuario.getCodUsuario(), mapColVlr);
        }    
        else {    
            msgRtrn = new FacesMessage(FacesMessage.SEVERITY_ERROR, null, getMessageI18N("W001"));            
        }
    }

    /* -----------------------------------------------------------------------
     * Envia Email para notificacao de nova senha
     * ---------------------------------------------------------------------- */            
    private void enviaEmail(String novaSenha) throws EaoException {
        EnviaEmail email = new EnviaEmail();
        List<String> msgsEmail = new ArrayList<String>();
        msgsEmail.add("Você está recebendo uma nova senha de acesso.");
        msgsEmail.add("Para sua segurança altere esta nova senha para uma de sua opção.");
        msgsEmail.add("Senha: ".concat(novaSenha));
        msgsEmail.add("Comunicação digital, favor não responder este email.");
        try {
            email.send(dadosUsuario.getDscEmail(),dadosUsuario.getNomUsuario(), 
                       "Nova Senha",msgsEmail);
        }
        catch (EmailException e) {
            throw new EaoException(e.getLocalizedMessage());
        }
    }
    
    /* -----------------------------------------------------------------------
     * Destroy session do Managed Bean
     * ---------------------------------------------------------------------- */            
    private void clearApplicationsSessionScope() {        
        Map<String, Object> mapAppSessionBean = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
        //Objetos de session
        mapAppSessionBean.put("recuperarSenhaBean",null);
      //mapAppSessionBean.put("questionarioSenhaBean",null);
    }

    /* -----------------------------------------------------------------------
     * Obtem a descricao da mensagem usando Internacionalizacao I18N
     * ---------------------------------------------------------------------- */                                
    private String getMessageI18N(String chaveMsg) {
        if (messageProvider == null  || !resourceBundleVar.equals(messageProvider.getResourceBundleVar()))
            messageProvider = new MessageProvider(resourceBundleVar);
        return messageProvider.getValueFromKey(chaveMsg);
    }
 
    /* -----------------------------------------------------------------------
     * Gera nova Senha
     * ---------------------------------------------------------------------- */                                
    private String getNovaSenhaRandom() {
        resourceBundleVar = SYSTEM_RESOURCE_BUNDLE_VAR;
        DecimalFormat df5 = new DecimalFormat("00000");
        Random random = new Random();
        String tokenSenha = getMessageI18N("system.tokenSenha");
        return tokenSenha.concat(df5.format(Math.abs(random.nextInt(10000))));
    }
}